package cn.com.twoke.easyproject.aspect.request.lock.hook.proceed;

import cn.com.twoke.easyproject.aspect.request.lock.RequestLock;
import cn.com.twoke.easyproject.common.utils.ExceptionUtils;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

@RequiredArgsConstructor
public class DistributedJoinPointProceed implements RequestLockKeyJoinPointProceed {

    private final RedissonClient redissonClient;

    @Override
    public Object proceed(String key, RequestLock requestLock, ProceedingJoinPoint joinPoint) throws Throwable {
        RLock lock = redissonClient.getLock(key);
        boolean isLocked = false;
        try {
            // 尝试抢占锁
            isLocked = lock.tryLock();
            // 没有拿到锁说明已经有请求了
            if (!isLocked) {
                ExceptionUtils.throwBusinessException(requestLock.message());
            }
            // 拿到锁后设置过期时间
            lock.lock(requestLock.expire(), requestLock.timeUnit());
            return joinPoint.proceed();
        } finally {
            if (isLocked && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

}
